/**
 * Copyright 2020 Tianshu AI Platform. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================
 */
package org.dubhe.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dubhe.admin.dao.AuthCodeMapper;
import org.dubhe.admin.domain.dto.AuthCodeQueryDTO;
import org.dubhe.admin.domain.entity.Auth;
import org.dubhe.admin.domain.entity.Permission;
import org.dubhe.admin.domain.vo.AuthVO;
import org.dubhe.admin.other.*;
import org.dubhe.admin.service.AuthCodeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description 权限组服务实现类
 * @date 2021-05-14
 */
@Service
public class AuthCodeServiceImpl extends ServiceImpl<AuthCodeMapper, Auth> implements AuthCodeService {

    @Autowired
    private AuthCodeMapper authCodeMapper;

    public final static List<String> FIELD_NAMES;

    static {
        FIELD_NAMES = ReflectionUtils.getFieldNames(AuthVO.class);
    }

    /**
     * 分页查询权限组信息
     *
     * @param authCodeQueryDTO 分页查询实例
     * @return Map<String, Object> 权限组分页信息
     */
    @Override
    public Map<String, Object> queryAll(AuthCodeQueryDTO authCodeQueryDTO) {

        // 1. 通过权限组id/auth_code,查询权限组对应的其他字段信息(description)
        //    SQL语句：SELECT id,auth_code,description,deleted,create_user_id,update_user_id,create_time,update_time FROM auth WHERE deleted=0 AND ((id = ? OR auth_code LIKE ?)) ORDER BY id DESC
        Page page = authCodeQueryDTO.toPage();                                                                  // 根据传入参数对象authCodeQueryDTO的toPage()方法，获取一个Page的对象
        QueryWrapper<Auth> queryWrapper = new QueryWrapper<>();                                                 // 新建一个以Auth类的查询包装类对象
        // 1.1 where条件
        if (StringUtils.isNotEmpty(authCodeQueryDTO.getAuthCode())) {                                           // 如果authCodeQueryDTO对象的authCode(授权名称)不为空
            queryWrapper.and(x -> x.eq("id", authCodeQueryDTO.getAuthCode()).or().like("auth_code", authCodeQueryDTO.getAuthCode()));           // where中：AND ((id = ? OR auth_code LIKE ?))
        }
        // 1.2 order排序
        IPage<Auth> groupList;                                                                                  // 声明一个变量,存储带分页信息的Auth类型的查询结果
        try {
            if (authCodeQueryDTO.getSort() != null && FIELD_NAMES.contains(authCodeQueryDTO.getSort())) {       // 如果authCodeQueryDTO对象排序字段不为空 且 authCodeQueryDTO对象的排序字段是AuthVO类中的属性
                if (StringConstant.SORT_ASC.equalsIgnoreCase(authCodeQueryDTO.getOrder())) {                    // 如果authCodeQueryDTO对象排序方式为asc(递增)
                    queryWrapper.orderByAsc(StringUtils.humpToLine(authCodeQueryDTO.getSort()));                    // 1.获取authCodeQueryDTO对象的排序字段(id,authCode...)    2.将其排序字段由驼峰转化为下划线(authCode -> auth_code)    3.按照排序字段的升序进行排序
                } else {                                                                                        // 如果authCodeQueryDTO对象排序方式为desc(递减)
                    queryWrapper.orderByDesc(StringUtils.humpToLine(authCodeQueryDTO.getSort()));                   // 1.获取authCodeQueryDTO对象的排序字段(id,authCode...)    2.将其排序字段由驼峰转化为下划线(authCode -> auth_code)    3.按照排序字段的降序进行排序
                }
            } else {                                                                                            // 如果authCodeQueryDTO对象排序字段为空 或 authCodeQueryDTO对象的排序字段不是AuthVO类中的属性
                queryWrapper.orderByDesc(StringConstant.ID);                                                        // 则默认按照id降序排列
            }
            groupList = authCodeMapper.selectPage(page, queryWrapper);                                         // 以queryWrapper为查询条件,将查询结果存储在page中,赋值给groupList对象  // ORDER BY id DESC
        } catch (Exception e) {
            throw new BusinessException("查询权限组列表展示异常");                                                 // 运行时异常则抛出“查询权限组列表展示异常”
        }


        // 2. 通过权限组id,获取对应权限id及字段信息
        //    SQL语句：select * from permission where id in (select permission_id from auth_permission where auth_id=#{authId}) and deleted=0 order by id
        // 将带分页信息的Auth列表 -> 带分页信息的AuthVO列表
        List<AuthVO> authResult = groupList.getRecords().stream().map(x -> {                                   // .getRecords():获取分页信息Auth的列表; .stream():将获取的记录列表转化为一个流,以支持后续流式操作; .map():对流中每一个元素进行操作,并返回一个新的元素（x代指的是Auth对象）
            AuthVO authVO = new AuthVO();                                                                      // 创建一个新的AuthVO的对象--解释Auth,Permission,AuthVo类
            BeanUtils.copyProperties(x, authVO);                                                               // 将流中的Auth对象的属性赋值给AuthVO对象
            List<Permission> permissions = authCodeMapper.getPermissionByAuthId(x.getId());                    // 1.获取Auth对象的id     2.通过authCodeMapper.getPermissionByAuthId()方法获取权限组id对应的权限列表
            authVO.setPermissions(permissions);                                                                // 将获取的权限列表赋值给authVO对象的permission属性
            return authVO;                                                                                     // 返回处理后的Auth对象
        }).collect(Collectors.toList());                                                                       // 将流中元素收集,形成一个AuthVO列表
        return PageUtil.toPage(page, authResult);}                                                              // 返回一个Map<String,Object>键值对
                                                                                                               // 数据格式：
                                                                                                               /*           {
                                                                                                                                "result" : "List<AuthVO>",
                                                                                                                                "page" : {
                                                                                                                             	        "current" : "currentPage",
                                                                                                                              	        "size" : "pageSize",
                                                                                                                                	    "total" : "totalPages"
                                                                                                                                 }
                                                                                                                             }
                                                                                                             */
}


